本節將介紹 Broker 的生命週期中,啟動 Broker 與停止 Broker 到底各自發生了什麼事情。
當一個 Broker 被啟動時,它將會嘗試與 Transporter 建立連線。建立完成後,它不會將本地服務清單發佈到遠端節點,而是先啟動所有的服務,然後呼叫每個服務中的 started 處理程序。待所有的服務都啟動成功後, Broker 才會將本地服務清單發佈到遠端節點。因此只有在所有本地服務都成功初始化並啟動後,遠端節點才能夠發送請求。

Fig. 1. 啟動 Broker 流程
當兩個服務互相依賴的時候,可能會陷入死結。例如:
users服務設定了dependencies: ["posts"],posts也設定了dependencies: ["users"]。為避免此狀況,請移除dependencies設定,改使用this.waitForServices來等待多個服務後再啟動。
補充,官方文件是寫在started執行,但筆者測試仍然會死結,建議可以檢查是否有架構設計上的缺陷,或可將微服務再做細分來避免此狀況,例如另外建立一個整合服務來等待兩個服務。
當呼叫 broker.stop 或停止處理程序時,首先 Broker 會透過 Transporter 發送空的服務列表,這時已停止的服務就不會繼續收到請求,而是將請求改送到其它的實例。接著 Broker 會開始停止所有的本地服務,最後中斷 Transporter 的連線並結束處理程序。

Fig. 2. 停止 Broker 流程
在介紹完 Broker 的生命週期後,本節將介紹服務的創建、啟動、停止與合併事件,以及該如何使用生命週期事件來做處理。
created 事件會在服務實例被創建時觸發。例如: broker.createService 、 broker.loadService 。
範例:在服務創建時建立 http 模組實例並存放於 this 中。
const http = require("http");
module.exports = {
    name: "www",
    created() {
        // 建立 HTTP 服務
        this.server = http.createServer(this.httpHandler);
    }
};
注意,這是個同步事件處理函數,不可以返回
Promise,也不可以使用async/await語法糖。
started 事件會在呼叫 broker.start 並啟動所有本地服務時被觸發。
範例:用於連線到資料庫。
module.exports = {
    name: "users",
    async started() {
        try {
            await this.db.connect();
        } catch(e) {
            throw new MoleculerServerError("Unable to connect to database.", e.message);
        }
    }
};
注意,這是個非同步事件處理函數,可以返回
Promise,也可以使用async/await語法糖。
stopped 事件會在呼叫 broker.stop 並停止所有本地服務時被觸發。
範例:用於中斷資料庫連線。
module.exports = {
    name: "users",
    async stopped() {
        try {
            await this.db.disconnect();
        } catch(e) {
            this.logger.warn("Unable to stop database connection gracefully.", e);
        }
    }
};
注意,這是個非同步事件處理函數,可以返回
Promise,也可以使用async/await語法糖。
merged 事件會在綱目 (包含 mixin ) 合併後被呼叫,呼叫完成後才會將服務註冊,因此你可以在這之前就先對其操作。
module.exports = {
    name: "posts",
    settings: {},
    actions: {
        find: {
            params: {
                limit: "number"
            },
            handler(ctx) {
                // ...
            }
        }
    },
    merged(schema) {
        // 修改服務設定
        schema.settings.myProp = "myValue";
        // 修改 Actions 的驗證參數
        schema.actions.find.params.offset = "number";
    }
};
[1] Lifecycle, https://moleculer.services/docs/0.14/lifecycle.html